package com.petter.gradlespringboot.proxy.rpc;

import java.io.File;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * rpc 代理
 * @author : GD
 * @date :2021/7/6 : 23:05
 */
public class RpcProxy {
    /**
     * @param port 启动端口
     * @param clazz 注册类
     */
    public void start(int port,String clazz){

        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(port);

            ExecutorService executorService = Executors.newFixedThreadPool(10);
            while (true){
                Socket client = serverSocket.accept();
                RpcService proxy = new RpcService(client,getService(clazz));
                executorService.execute(proxy);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(serverSocket != null){
                try {
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public Map<String,Object> getService(String clazz) {
        try {
            Map<String, Object> services = new HashMap<String, Object>();
            //获取所有服务类
            String[] clazzes = clazz.split(",");
            List<Class<?>> classes = new ArrayList<Class<?>>();
            for (String cl : clazzes) {
                List<Class<?>> classList = getClasses(cl);
                classes.addAll(classList);
            }
            //循环实例化
            for (Class<?> cla : classes) {
                Object obj = cla.newInstance();
                services.put(cla.getAnnotation(RpcServiceFlag.class).value().getName(), obj);
            }
            return services;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public static List<Class<?>> getClasses (String pckgname) throws ClassNotFoundException {
        List<Class<?>> classes = new ArrayList<Class<?>>();
        File directory = null;
        try {
            ClassLoader cld = Thread.currentThread().getContextClassLoader();
            if (cld == null){
                throw new ClassNotFoundException("Can't get class loader.");
            }
            String path = pckgname.replace('.', '/');
            URL resource = cld.getResource(path);
            if (resource == null){
                throw new ClassNotFoundException("No resource for " + path);
            }
            directory = new File(resource.getFile());
        } catch (NullPointerException x) {
            throw new ClassNotFoundException(pckgname + " (" + directory + ") does not appear to be a valid package a");
        }
        if (directory.exists()) {
            //获取所有文件
            String[] files = directory.list();
            File[] fileList = directory.listFiles();
            for (int i = 0; fileList != null && i < fileList.length; i++) {
                File file = fileList[i];
                //判断是否是Class文件
                if (file.isFile() && file.getName().endsWith(".class")) {
                    Class<?> clazz = Class.forName(pckgname + '.' + files[i].substring(0, files[i].length() - 6));
                    if (clazz.getAnnotation(RpcServiceFlag.class) != null) {
                        classes.add(clazz);
                    }
                } else if (file.isDirectory()) { //如果是目录，递归查找
                    List<Class<?>> result = getClasses(pckgname + "." + file.getName());
                    if (result != null && result.size() != 0) {
                        classes.addAll(result);
                    }
                }
            }
        } else {
            throw new ClassNotFoundException(pckgname + " does not appear to be a valid package b");
        }
        return classes;
    }

}
